class Bitmap32
{
public:
    // typedef a pixel type.  Since this is 32-bit, we'll want a 32bit data type
    //   on Windows, we can use DWORD
    typedef DWORD       pixel_t;
    
private:
    // data members:
    HBITMAP   bmp;      // the actual bitmap
    HDC       dc;       // the host DC
    HBITMAP   bmpold;   // the host's original bitmap (for cleanup purposes)
    
    pixel_t*  pix;      // pointer to the pixel data
    
    int       pitch;    // pitch of the image (in pixel_t's, not in bytes!
                        //    so technically it's not the pitch)
                        
    int       width;    // width of the bitmap
    int       height;   // height of the bitmap
    
public:
    //========================================
    //  Constructors
    Bitmap32()        // default ctor -- no image
    {
        Zero();
    }
    
    Bitmap32(int wd,int ht)     // creates a wd*ht bitmap
    {
        Zero();
        Create(wd,ht);
    }
    
    //========================================
    //  Destructor
    ~Bitmap32()
    {
        Destroy();
    }
    
    //========================================
    //  Resizing the bitmap
    //   note that doing this will destroy the contents of the bitmap
    void SetSize(int wd,int ht)
    {
        Destroy();
        Create(wd,ht);
    }
    
    //========================================
    //  Getting information about the bitmap
    inline int GetWidth() const         { return width;     }
    inline int GetHeight() const        { return height;    }
    inline int GetPitch() const         { return pitch;     }
    inline bool IsOk() const            { return pix != 0;  }   // returns true if
                                                                //  the bitmap is ok for drawing

    //========================================
    //  Getting the DC for drawing
    //      (I don't know if const correctness works here -- not sure how
    //  HDC is defined)
    inline const HDC GetDC() const      { return dc;        }
    inline HDC GetDC()                  { return dc;        }
    
    //========================================
    //  Pixel level access - getting setting individual pixels
    //    Note there's no bounds checking here for speed purposes
    //  so be sure to check that yourself
    inline pixel_t operator () (int x,int y) const  { return pix[ (y*pitch) + x ];  }
    inline pixel_t& operator () (int x,int y)       { return pix[ (y*pitch) + x ];  }
    
    //=========================================
    //  Getting the pixel buffer
    //    Alternative to the above operator () approach.  Potentially faster for
    //  drawing large groups of pixels since you don't have to do (y*pitch) for every
    //  access.  Although easier to misuse and therefore less safe.  Pick your poison.
    inline const pixel_t* GetPixels() const { return pix; }
    inline pixel_t* GetPixels()             { return pix; }
    

private:
    //=========================================
    //=========================================
    //  The "inner workings"
    
    void Zero()
    {
        bmp =       0;
        dc =        0;
        bmpold =    0;
        pix =       0;
        pitch =     0;
        width =     0;
        height =    0;
    }
    
    //=========================================
    void Destroy()
    {
        if(!IsOk())
            return;     // nothing to destroy
        
        SelectObject(dc,bmpold);    // put the old bmp in the dc
        DeleteDC(dc);               // then clean up the dc
        DeleteObject(bmp);          // and the dibsection
    }
    
    //=========================================
    void Create(int wd,int ht)
    {
        // make sure the dims are valid
        if((wd <= 0) || (ht <= 0))
        {
            // invalid dims
            Zero();
            return;
        }
                
        // Step 1:  Prep a BITMAPINFO structure
        BITMAPINFO bi;
        memset(&bi,0,sizeof(BITMAPINFO));       // zero memory for good measure
        
        bi.bmiHeader.biSize =       sizeof(BITMAPINFOHEADER);
        bi.bmiHeader.biWidth =      wd;
        bi.bmiHeader.biHeight =     -ht;  // windows bitmaps are upside down unless the height is negative
        bi.bmiHeader.biPlanes =     1;
        bi.bmiHeader.biBitCount =   32;
        
        // Step 2:  Create the dib section
        bmp = CreateDIBSection(0,&bi,DIB_RGB_COLORS,(void**)(&pix),0,0);
        if(!bmp)        // failure is unlikely... but just in case
        {
            Zero();     // maybe throwing an exception would be a better option
            return;     //  than silent failure.  But I'm lazy
        }
        
        // Step 3:  Create the DC
        dc = CreateCompatibleDC(0);
        
        // Step 4:  put the dib section in the dc
        bmpold = (HBITMAP)SelectObject(dc,bmp);
        
        // Step 5:  record other tidbits
        width = wd;
        height = ht;
        pitch = width;      // this just happens to work out on 32-bit bitmaps
        
        // all done
    }
    
    //==================================
    //  copy ctor and assignment operator
    //   private with no bodies to prevent unwanted copying
    Bitmap32(const Bitmap32&);
    Bitmap32& operator = (const Bitmap32&);
};